﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Ivi.ConfigServer.Interop;
using Ivi.Driver.Interop;
using System.Runtime.InteropServices;
using Ivi.Visa.Interop;
using System.Diagnostics;

namespace AIRO.Devices
{
    [Guid("801D3738-447A-11DD-8DF9-BACA55D89593")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("MyDevices.BasicIviDriverVisa")]
    public abstract class BasicIviDriverVisa:BasicIviDriver
    {
        //protected MessageBasedSession mbSession;
        protected Ivi.Visa.Interop.ResourceManager ioMgr;
        protected Ivi.Visa.Interop.FormattedIO488 instrument;

        public BasicIviDriverVisa()
            : base()
        {
            ioMgr = new Ivi.Visa.Interop.ResourceManagerClass();
            instrument = new Ivi.Visa.Interop.FormattedIO488Class();
        }

        public virtual void Close()
        {
            if (_initialized)
            {
                
                //mbSession.Dispose();
                instrument.IO.Close();
                _initialized = false;
                
            }
            else
            {
                iviDriverErrorQueue.Enqueue(new Error(IviDriver_ErrorCodes.E_IVI_NOT_INITIALIZED));
                throw new Exception("Driver is not initialized");
            }
        }

        protected virtual void InitVisaMessageBasedSession(string ResourceName)
        {
            string addressStringGrammar = @"(VXI\d*(::\.+(::INSTR)?)|(::MEMACC)|((::\.+)?::BACKPLANE)|(::SERVANT))|(GPIB-VXI\d*(::\.+(::INSTR)?)|(::MEMACC)|((::\.+)?::BACKPLANE))|(GPIB\d*::(\.+(::\.+)?(::INSTR)?)|(INTFC)|(SERVANT))|(ASRL\d*(::INSTR)?)|(TCPIP\d*((::\.+)?::SERVANT)|(::\.+(::\.+)?(::INSTR)?)|(::\.+::\d+::SOCKET))|(USB\d*::\.+::\.+::\.+(::\.+)?(::INSTR)?)|(PXI\d*(::\.+(::\.+)?(::INSTR)?)|(::\d+-\d+(.function)?(::INSTR)?)|(::CHASSIS\d+::SLOT\d+(::FUNC\.+)?(::INSTR)?)|(::MEMACC))";
            Regex addressStringGrammarRegex = new Regex(addressStringGrammar, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.Singleline);
            if (addressStringGrammarRegex.IsMatch(ResourceName))
            {
                #region VisaResourceName
                resourceName = ResourceName;
                try
                {
                    //mbSession = (MessageBasedSession)ResourceManager.GetLocalManager().Open(resourceName);
                    //mbSession.Timeout = 1000;
                    instrument.IO = (IMessage)ioMgr.Open(resourceName,AccessMode.EXCLUSIVE_LOCK,1000,"");
                    instrument.IO.Timeout = 10000;
                }
                catch (InvalidCastException)
                {
                    //MessageBox.Show("Resource selected must be a message-based session");
                    //return;
                    throw;
                }
                catch (Exception exp)
                {
                    //MessageBox.Show(exp.Message);
                    //return;
                    throw;
                }
                #endregion
            }
            else
            {
                #region LogicalName
                _logicalName = ResourceName;
                IviDriverSession iviSession = ReadConfigStore();
                try
                {
                    //mbSession = (MessageBasedSession)ResourceManager.GetLocalManager().Open(resourceName);
                    instrument.IO = (IMessage)ioMgr.Open(resourceName, AccessMode.EXCLUSIVE_LOCK, 5000, "");
                    instrument.IO.Timeout = 5000;
                    //instrument.IO.Clear();
                }
                catch (InvalidCastException)
                {
                    //MessageBox.Show("Resource selected must be a message-based session");
                    //return;
                    throw new Exception("Resource selected must be a message-based session");
                }
                catch (Exception exp)
                {
                    //MessageBox.Show(exp.Message);
                    //return;
                    throw;
                }
                IIviStructure confInitialSettings = (IIviStructure)iviSession.DataComponents["Configurable Initial Settings"];
                
                ConfigureInitialSettings(confInitialSettings);
                #endregion

            }
            
        }

        

        protected virtual void ConfigureInitialSettings(IIviStructure confInitialSettings)
        {

        }

        protected string ReplaceCommonEscapeSequences(string s)
        {
            return s.Replace("\\n", "\n").Replace("\\r", "\r");
        }

        protected string InsertCommonEscapeSequences(string s)
        {
            return s.Replace("\n", "\\n").Replace("\r", "\\r");
        }

        protected string Trim(string s)
        {
            char[] charsToTrim = { '\n', '\r' };
            return s.Trim(charsToTrim);
        }

        protected virtual string Query(string cmd)
        {
            string textToWrite = ReplaceCommonEscapeSequences(cmd);
            //string responseString = InsertCommonEscapeSequences(mbSession.Query(textToWrite));
            string responseString;
            lock (instrument.IO)
            {
                //responseString = Trim(mbSession.Query(textToWrite));
                instrument.IO.WriteString(textToWrite);
                Debug.WriteLine("Write: " + textToWrite);
                responseString = Trim(instrument.ReadString());
                Debug.WriteLine("Read: " + responseString);
            }
            return responseString;
        }

        protected virtual void SendCommand(string cmd)
        {
            string textToWrite = ReplaceCommonEscapeSequences(cmd);
            lock (instrument.IO)
            {                
                instrument.IO.WriteString(textToWrite);
                Debug.WriteLine("Write: " + textToWrite);
            }
        }

        
    }
}
